/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.util;

/**
 * <p>这个类提供了Set接口的骨架实现，来最小化实现这个接口的努力。
 * 
 * <p>通过继承这个类的过程来实现set，与继承AbstractCollection来实现Collection的过程一样，
 * 除了所有的方法和构造器必须遵守Set接口的额外规定。（例如add方法必须不允许重复地加入相同的对象到set）
 * 
 * <p>注意：这个类没有覆盖AbstractCollection的方法。
 * 它仅仅增加了equals和hashCode和removeAll方法的实现。
 *
 *
 * @param <E> the type of elements maintained by this set
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see Collection
 * @see AbstractCollection
 * @see Set
 * @since 1.2
 */

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractSet() {
    }

    // Comparison and hashing

    /**
     * <p>将指定对象与这个set，进行相等性的比较。
     * 如果指定对象也是一个set，两个set有相同的大小，指定set的每个成员，都被这个set包含
     * （相同的，这个set的每个成员，都被指定set包含），返回true。
     * 这个定义保证equals方法在不同set接口的实现中，工作正常。
     *
     * <p>这个实现首先检查指定对象是否是自己，如果是，返回true。
     * 然后，检查指定对象是否是一个大小与自己相同的set，如果不是，返回false。
     * 如果这样，返回containsAll((Collection) o)的结果。
     *
     * @param o object to be compared for equality with this set
     * @return <tt>true</tt> if the specified object is equal to this set
     */
    public boolean equals(Object o) {
        if (o == this) // 自己
            return true;

        if (!(o instanceof Set)) // set类型
            return false;
        Collection<?> c = (Collection<?>) o;
        if (c.size() != size()) // 大小
            return false;
        try {
            return containsAll(c); // containsAll
        } catch (ClassCastException unused)   {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
    }

    /**
     * 返回这个set的hashcode。
     * set的hashcode与这个set中元素的hashcode的和相同。
     * null元素的hashcode为0.
     * 这保证对于两个set，s1和s2，s1.equals(s2)
     * 意味着s1.hashCode()==s2.hashCode()，如Object的hashcode的通常约定。
     *
     * <p>这个实现迭代这个set，调用set中每个集合的hashCode方法，将结果加起来。
     *
     * @return the hash code value for this set
     * @see Object#equals(Object)
     * @see Set#equals(Object)
     */
    public int hashCode() {
        int h = 0;
        Iterator<E> i = iterator();
        while (i.hasNext()) {
            E obj = i.next(); // 迭代器不断next
            if (obj != null) // null，不加，即加0
                h += obj.hashCode();  // 加元素的hashCode
        }
        return h;
    }

    /**
     * 删除这个set中，所有已经包含在指定集合的元素（可选操作）。
     * 如果指定集合也是一个set，这个集合的结果是两个集合的不对称差异。
     *
     * <p>这个实现，调用两者的size方法，确定这个set和指定集合哪个更小。
     * 
     * 如果这个set有更少的元素，实现迭代这个set，检查Iterator返回的每个元素，是否被指定集合包含。
     * 如果被包含，调用Iterator的remove方法删除它。
     * 
     * 如果指定集合有更少的元素，这个实现迭代指定集合，调用这个set的remove方法，移除Iterator返回的每个元素。
     *
     * <p>注意：如果Iterator没有实现remove方法，会抛出UnsupportedOperationException
     *
     * @param  c collection containing elements to be removed from this set
     * @return <tt>true</tt> if this set changed as a result of the call
     * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
     *         is not supported by this set
     * @throws ClassCastException if the class of an element of this set
     *         is incompatible with the specified collection
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this set contains a null element and the
     *         specified collection does not permit null elements
     * (<a href="Collection.html#optional-restrictions">optional</a>),
     *         or if the specified collection is null
     * @see #remove(Object)
     * @see #contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;

        if (size() > c.size()) { // 指定集合的元素少
            for (Iterator<?> i = c.iterator(); i.hasNext(); )
                modified |= remove(i.next()); // 调用这个set的remove方法，移除Iterator返回的每个元素
        } else { // 这个set元素少
            for (Iterator<?> i = iterator(); i.hasNext(); ) {
                if (c.contains(i.next())) { // 实现迭代这个set，检查Iterator返回的每个元素，是否被指定集合包含
                    i.remove(); // 如果被包含，调用Iterator的remove方法删除它
                    modified = true;
                }
            }
        }
        return modified;
    }

}
